#include "QSketchManager.h"

#include <gp_Ax3.hxx>
#include "QSketch.h"
#include "Core/MainWindow.h"
#include "Render/WindowInteractorStyle.h"
#include <vtkPlane.h>
#include <vtkCoordinate.h>
#include "Sketch/Action/QSketchCurveAction.h"
#include "Sketch/Action/QSketchLineAction.h"
#include "Sketch/Action/QSketchCircleAction.h"
#include "Sketch/Action/QSketchArcCircleAction.h"
#include "Sketch/Action/QSketchRectangleAction.h"
#include "Core/RWTools.h"
#include "Render/QIVtkSelectionPipeline.h"
#include <TopoDS.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Edge.hxx>
#include <TopExp.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <ShapeFix_Wire.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include "FeatureShape/ShapeOperation.h"
#include "FeatureShape/HistoryManager.h"
#include <BRepAdaptor_Curve.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <gp_Lin.hxx>
#include <Adaptor3d_Curve.hxx>
#include <Geom_Circle.hxx>
#include "Serialize/RWShapeSerializeManager.h"

// #TODO: 存在资源泄露, actor只是被隐藏而非删除，为了性能考虑，暂不处理

struct PntComparator 
{
	bool operator()(const gp_Pnt& p1, const gp_Pnt& p2) const 
	{
		if (p1.IsEqual(p2, 0.01))
		{
			return false;
		}
		if (!IsNearlyEqual(p1.X(), p2.X()), 0.01) return p1.X() < p2.X();
		if (!IsNearlyEqual(p1.Y(), p2.Y()), 0.01) return p1.Y() < p2.Y();
		if (!IsNearlyEqual(p1.Z(), p2.Z()), 0.01) return p1.Z() < p2.Z();
		return false;
	}
};

QSketchManager::QSketchManager(MainWindow* mainWindow)
	: m_mainWindow(mainWindow)
{
	m_currentSketch = nullptr;
	m_currentCurveAction = nullptr;

	m_curveActions[ESketchCurveType::Line] = new QSketchLineAction(this, m_mainWindow);
    m_curveActions[ESketchCurveType::Circle] = new QSketchCircleAction(this, m_mainWindow);
    m_curveActions[ESketchCurveType::ArcCircle] = new QSketchArcCircleAction(this, m_mainWindow);
	m_curveActions[ESketchCurveType::Rectangle] = new QSketchRectangleAction(this, m_mainWindow);

	connect(m_mainWindow, &MainWindow::OnMouseMove, this, &QSketchManager::OnMouseMove);
	connect(m_mainWindow, &MainWindow::OnLeftButtonDown, this, &QSketchManager::OnLeftButtonDown);
	connect(m_mainWindow, &MainWindow::OnPickActor, this, &QSketchManager::PickActor);

	_selectedVertexTypes.insert(EVertexType::EdgeEndVertex);
	_selectedVertexTypes.insert(EVertexType::EdgeDividedVertex);
	_selectedVertexTypes.insert(EVertexType::IntersectionVertex);
	_selectedVertexTypes.insert(EVertexType::CircleCenterVertex);
	_selectedVertexTypes.insert(EVertexType::RandomVertex);

	tempSphereActor = m_mainWindow->CreateTempSphereActor(0.015f, gp_Pnt());
	tempSphereActor->SetVisibility(false);
	tempSphereActor->SetPickable(false);
}

QSketchManager::~QSketchManager()
{}

void QSketchManager::OnMouseMove(Standard_Integer theX, Standard_Integer theY)
{
	//std::cout << "QSketchManager::MouseMove: " << theX << ", " << theY << std::endl;

	if (m_curActionState == ESketchActionState::None || m_currentSketch == nullptr)
	{
		if (tempSphereActor && tempSphereActor->GetVisibility())
		{
			tempSphereActor->SetVisibility(false);
			m_mainWindow->FlushRender();
		}
		return;
	}

	tempSphereActor->SetVisibility(false);
	vtkRenderer* renderer = m_mainWindow->GetRenderer();

	// 使用 vtkCoordinate 转换坐标
	vtkNew<vtkCoordinate> coordinateNear;
	coordinateNear->SetCoordinateSystemToDisplay();
	coordinateNear->SetValue(theX, theY, 0.0); // 近剪裁平面 (z=0)
	double* worldNear = coordinateNear->GetComputedWorldValue(renderer);

	vtkNew<vtkCoordinate> coordinateFar;
	coordinateFar->SetCoordinateSystemToDisplay();
	coordinateFar->SetValue(theX, theY, 1.0); // 远剪裁平面 (z=1)
	double* worldFar = coordinateFar->GetComputedWorldValue(renderer);

	// 射线起点 (P0) 和终点 (P1)
	double P0[3] = { worldNear[0], worldNear[1], worldNear[2] };
	double P1[3] = { worldFar[0], worldFar[1], worldFar[2] };

	// 定义平面
	double O[3] = { m_currentSketch->m_O.X(), m_currentSketch->m_O.Y(), m_currentSketch->m_O.Z()}; // 平面原点
	double N[3] = { m_currentSketch->m_N.X(), m_currentSketch->m_N.Y(), m_currentSketch->m_N.Z()}; // 平面法向量

	// 创建平面对象
	vtkNew<vtkPlane> plane;
	plane->SetOrigin(O);
	plane->SetNormal(N);

	// 计算交点
	double t;
	double intersection[3];
	int intersected = plane->IntersectWithLine(P0, P1, t, intersection);

	if (intersected) 
	{
		m_currentIntersectionPoint = gp_Pnt(intersection[0], intersection[1], intersection[2]);
		bool bFind = false;
		for (const auto& item : m_points)
		{
			if (!_selectedVertexTypes.count(item.first)) continue;
			gp_Pnt findPoint;
			bFind = ContainsVertex(findPoint, item.second, m_currentIntersectionPoint, 0.01);
			if (bFind)
			{
				tempSphereActor->SetPosition(findPoint.X(), findPoint.Y(), findPoint.Z());
				tempSphereActor->SetVisibility(true);
				m_currentIntersectionPoint = findPoint;
				break;
			}
		}

		if ((bFind || _selectedVertexTypes.count(EVertexType::RandomVertex)) && m_currentCurveAction)
		{
			m_currentCurveAction->OnMouseMove(m_currentIntersectionPoint);
		}
		else
		{
			// z值大于0，代表当前选点无效
			m_currentIntersectionPoint.SetZ(2);
		}
	}

	// 检测actor


	m_mainWindow->FlushRender();
}

void QSketchManager::OnLeftButtonDown()
{
	//std::cout << "QSketchManager::OnLeftButtonDown" << std::endl;

	if (m_curActionState == ESketchActionState::CreateCurve)
	{
		if (!m_currentSketch || !m_currentCurveAction)
		{
			return;
		}
		// 选点有效
		if (m_currentCurveAction && m_currentIntersectionPoint.Z() < 1)
		{
			m_currentCurveAction->OnLeftDown(m_currentIntersectionPoint);
		}
	}
	else if (m_curActionState == ESketchActionState::TrimCurve)
	{
		if (!m_actionCurveActor)
		{
			return;
		}

		// 1.获得选择的edge, 只有长方体是复合曲线
		TopoDS_Edge originalEdge = GetSelectedEdge();
		if (originalEdge.IsNull())
		{
			return;
		}
		// 获取端点参数
		Standard_Real uStart, uEnd;
		Handle(Geom_Curve) curve = BRep_Tool::Curve(originalEdge, uStart, uEnd);
		Standard_Real uSelect = GeomAPI_ProjectPointOnCurve(m_currentIntersectionPoint, curve).LowerDistanceParameter();
		Standard_Real u1 = uStart;
        Standard_Real u2 = uEnd;

		// 2.获得在这条直线上且距离当前屏幕交点最近的两个点
		std::vector<gp_Pnt> points = m_pipelineIntersectionPoints[m_actionCurveActor->GetShapeID()];
		for (const auto& point : points)
		{
			if (!IsPointOnEdge(point, originalEdge, 0.01))
			{
				continue;
			}
			GeomAPI_ProjectPointOnCurve projector(point, curve);
			Standard_Real u = projector.LowerDistanceParameter();
			if (u < uSelect && u > u1)
			{
				u1 = u;
			}
			else if (u > uSelect && u < u2)
			{
				u2 = u;
			}
		}

		// 创建首段曲线
		if (!IsNearlyEqual(uStart, u1))
		{
			Handle(Geom_TrimmedCurve) trimmedCurve1 = new Geom_TrimmedCurve(curve, uStart, u1);
			TopoDS_Edge newEdge1 = BRepBuilderAPI_MakeEdge(trimmedCurve1);
			Handle(QIVtkSelectionPipeline) newActor = m_mainWindow->createBasicUnitActor(newEdge1);
			// 缓存交点
			for (const auto& point : points)
			{
				Standard_Real u = GeomAPI_ProjectPointOnCurve(point, curve).LowerDistanceParameter();
				if (u > uStart && u < u1)
				{
                    m_pipelineIntersectionPoints[newActor->GetShapeID()].push_back(point);
				}
			}
			newActor->m_featureShape.reset(new FeatureShapeMix(newEdge1, RWShapeSerializeManager::ConstructFilename()));
			newActor->Actor()->GetProperty()->SetLineWidth(3);
			m_currentSketch->m_actors.push_back(newActor);
		}
		// 创建尾段曲线
		if (!IsNearlyEqual(uEnd, u2))
		{
            Handle(Geom_TrimmedCurve) trimmedCurve2 = new Geom_TrimmedCurve(curve, u2, uEnd);
            TopoDS_Edge newEdge2 = BRepBuilderAPI_MakeEdge(trimmedCurve2);
			Handle(QIVtkSelectionPipeline) newActor = m_mainWindow->createBasicUnitActor(newEdge2);
			// 缓存交点
			for (const auto& point : points)
			{
				Standard_Real u = GeomAPI_ProjectPointOnCurve(point, curve).LowerDistanceParameter();
                if (u > u2 && u < uEnd)
				{
                    m_pipelineIntersectionPoints[newActor->GetShapeID()].push_back(point);
				}
			}
			newActor->m_featureShape.reset(new FeatureShapeMix(newEdge2, RWShapeSerializeManager::ConstructFilename()));
			newActor->Actor()->GetProperty()->SetLineWidth(3);
			m_currentSketch->m_actors.push_back(newActor);
		}

		// 删除旧actor交点缓存
		m_pipelineIntersectionPoints.erase(m_actionCurveActor->GetShapeID());
		m_mainWindow->RemoveActorFromRenderer(m_actionCurveActor);
		RemoveActor(m_currentSketch->m_actors, m_actionCurveActor);
		m_mainWindow->FlushRender();
		m_actionCurveActor = nullptr;
		m_currentSketch->m_deletedActors.clear();
        //m_curActionState = ESketchActionState::None;
	}
	else if (m_curActionState == ESketchActionState::ExtendCurve)
	{
		// 1.获得选择的edge, 只有长方体是复合曲线
		TopoDS_Edge edgeToExtend = GetSelectedEdge();
		if (edgeToExtend.IsNull())
		{
			qDebug() << "ExtendCurve: No edge selected";
			//m_curActionState = ESketchActionState::None;
			return;
		}

		TopoDS_Edge targetEdge;
		double nearestDistance = 999999;
		// 2.获得延伸的目标曲线——当前屏幕点距离最近的曲线
		for (auto& actor : m_currentSketch->m_actors)
		{
            if (actor->GetShapeID() == m_actionCurveActor->GetShapeID())
			{
				continue;
			}
			// 循环遍历长方体的每条边，判断点是否在线上
			TopExp_Explorer edgeExp(actor->OccShape(), TopAbs_EDGE);
			while (edgeExp.More())
			{
				TopoDS_Edge edge = TopoDS::Edge(edgeExp.Current());
				auto distance = DistancePointToEdgeGeometric(m_currentIntersectionPoint, edge);
				if (distance < nearestDistance)
				{
					nearestDistance = distance;
					targetEdge = edge;
				}
				edgeExp.Next();
			}
		}
		if (targetEdge.IsNull())
		{
            qDebug() << "ExtendCurve: No target edge found";
			//m_curActionState = ESketchActionState::None;
            return;
		}

		// 3.获得延伸曲线的几何信息
		Standard_Real uStartExtend, uEndExtend;
		Handle(Geom_Curve) extendCurve = BRep_Tool::Curve(edgeToExtend, uStartExtend, uEndExtend);
		GeomAPI_ProjectPointOnCurve projector(m_currentIntersectionPoint, extendCurve);
		Standard_Real uSelected = projector.LowerDistanceParameter();
		// 4.判断是从终点还是起点延伸
		gp_Pnt extendFirstPnt, extendLastPnt;
		extendFirstPnt = extendCurve->Value(uStartExtend);
        extendLastPnt = extendCurve->Value(uEndExtend);
		double p1D = DistancePointToEdgeGeometric(extendFirstPnt, targetEdge);
		double p2D = DistancePointToEdgeGeometric(extendLastPnt, targetEdge);
		Standard_Boolean bExtendFromStart = p1D > p2D;// 离哪个端点更近

		// 5.获得目标曲线的几何信息
		Standard_Real uStartTarget, uEndTarget;
		gp_Pnt targetFirstPnt, targetLastPnt;
		Handle(Geom_Curve) targetCurve = BRep_Tool::Curve(targetEdge, uStartTarget, uEndTarget);
        targetFirstPnt = targetCurve->Value(uStartTarget);
        targetLastPnt = targetCurve->Value(uEndTarget);

		TopoDS_Edge newExtendEdge;
		TopoDS_Edge newTargetEdge;

		// 6.将直线增长，将圆弧转化为整个圆
		GeomAdaptor_Curve adaptor(extendCurve);
		if (adaptor.GetType() == GeomAbs_Circle)
		{
			newExtendEdge = GetArcBasic(edgeToExtend);
		}
		else if (adaptor.GetType() == GeomAbs_Line)
		{
			newExtendEdge = ExtendEdge(edgeToExtend);
		}
		adaptor = GeomAdaptor_Curve(targetCurve);
		if (adaptor.GetType() == GeomAbs_Circle)
		{
			newTargetEdge = GetArcBasic(targetEdge);
		}
		else if (adaptor.GetType() == GeomAbs_Line)
		{
			newTargetEdge = ExtendEdge(targetEdge);
		}

		if (newTargetEdge.IsNull() || newExtendEdge.IsNull())
		{
			qDebug() << "ExtendCurve: Failed to create new edge";
			//m_curActionState = ESketchActionState::None;
            return;
		}
		// 7.计算交点
		auto intersectPoints = GetEdgeIntersections(newTargetEdge, newExtendEdge);
		TopoDS_Edge newEdge;
		Standard_Real u;
		if (intersectPoints.size() == 0)
		{
            qDebug() << "ExtendCurve: No intersection points found";
			//m_curActionState = ESketchActionState::None;
			return;
		}
		else if (intersectPoints.size() == 1)
		{
			GeomAPI_ProjectPointOnCurve projector(intersectPoints[0], extendCurve);
			u = projector.LowerDistanceParameter();
			Handle(Geom_TrimmedCurve) trimmedCurve;
			if (bExtendFromStart)
			{
				trimmedCurve = new Geom_TrimmedCurve(extendCurve, uStartExtend, u);
			}
			else
			{
                trimmedCurve = new Geom_TrimmedCurve(extendCurve, u, uEndExtend);
			}
			newEdge = BRepBuilderAPI_MakeEdge(trimmedCurve);
		}
		else // 判断最近交点
		{
			gp_Pnt nearestPoint;
			double nearestDistance = 999999;
			for (auto& point : intersectPoints)
			{
				double distance = m_currentIntersectionPoint.Distance(point);
                if (distance < nearestDistance)
				{
					nearestDistance = distance;
					nearestPoint = point;
				}
			}
			GeomAPI_ProjectPointOnCurve projector(nearestPoint, extendCurve);
			u = projector.LowerDistanceParameter();
			Handle(Geom_TrimmedCurve) trimmedCurve;
			if (bExtendFromStart)
			{
				trimmedCurve = new Geom_TrimmedCurve(extendCurve, uStartExtend, u);
			}
			else
			{
				trimmedCurve = new Geom_TrimmedCurve(extendCurve, u, uEndExtend);
			}
			newEdge = BRepBuilderAPI_MakeEdge(trimmedCurve);
		}

		if (newEdge.IsNull())
		{
            qDebug() << "ExtendCurve: Failed to create new edge";
			//m_curActionState = ESketchActionState::None;
            return;
		}
		// 8.创建新的曲线
		Handle(QIVtkSelectionPipeline) newActor = m_mainWindow->createBasicUnitActor(newEdge);
		newActor->m_featureShape.reset(new FeatureShapeMix(newEdge, RWShapeSerializeManager::ConstructFilename()));
		newActor->Actor()->GetProperty()->SetLineWidth(3);
		m_currentSketch->m_actors.push_back(newActor);
		std::vector<gp_Pnt> newIntersectPoints = m_pipelineIntersectionPoints[m_actionCurveActor->GetShapeID()];
		intersectPoints.push_back(extendCurve->Value(u));
		m_pipelineIntersectionPoints[newActor->GetShapeID()] = newIntersectPoints;

		m_pipelineIntersectionPoints.erase(m_actionCurveActor->GetShapeID());
		m_mainWindow->RemoveActorFromRenderer(m_actionCurveActor);
		RemoveActor(m_currentSketch->m_actors, m_actionCurveActor);
		m_mainWindow->FlushRender();
		m_actionCurveActor = nullptr;
		m_currentSketch->m_deletedActors.clear();
		//m_curActionState = ESketchActionState::None;
	}
}

void QSketchManager::PickActor(vtkActor* actor)
{
	if (m_curActionState != ESketchActionState::TrimCurve &&
		m_curActionState != ESketchActionState::ExtendCurve)
	{
		return;
	}

	if (!m_currentSketch)
	{
		return;
	}

	for (auto& pipeline : m_currentSketch->m_actors)
	{
		if (pipeline->Actor() == actor)
		{
			m_actionCurveActor = pipeline;
			return;
		}
	}
}

void QSketchManager::HandleEdgeIntersections(Handle(QIVtkSelectionPipeline) actor)
{
	TopExp_Explorer edgeExp(actor->OccShape(), TopAbs_EDGE);
	while (edgeExp.More())
	{
		TopoDS_Edge edge = TopoDS::Edge(edgeExp.Current());
		for (const auto& otherActor : m_currentSketch->m_actors)
		{
			// 首先判断包围盒是否相交
			if (!IsBoundingBoxesIntersect(edge, otherActor->OccShape()))
			{
				continue;
			}
			TopExp_Explorer other_edgeExp(otherActor->OccShape(), TopAbs_EDGE);
			while (other_edgeExp.More())
			{
				auto intersections = GetEdgeIntersections(edge, TopoDS::Edge(other_edgeExp.Current()));
				// 空间换时间
				m_points[EVertexType::IntersectionVertex].insert(m_points[EVertexType::IntersectionVertex].end(),
					intersections.begin(), intersections.end());
				other_edgeExp.Next();
				// 增加actor的关联交点
				m_pipelineIntersectionPoints[otherActor->GetShapeID()].insert(
					m_pipelineIntersectionPoints[otherActor->GetShapeID()].end(), intersections.begin(), intersections.end());
                m_pipelineIntersectionPoints[actor->GetShapeID()].insert(
					m_pipelineIntersectionPoints[actor->GetShapeID()].end(), intersections.begin(), intersections.end());
			}
		}
		edgeExp.Next();
	}
}

void QSketchManager::TrimCurve()
{
	ClearActionState();
	m_curActionState = ESketchActionState::TrimCurve;
}

void QSketchManager::ExtendCurve()
{
	ClearActionState();
    m_curActionState = ESketchActionState::ExtendCurve;
}

void QSketchManager::ClearActionState()
{
	if (m_curActionState == ESketchActionState::CreateCurve)
	{
		if (m_currentCurveAction)
		{
			m_currentCurveAction->Reset();
		}
	}
	//else if (m_curActionState == ESketchActionState::TrimCurve)
	//{

	//}

	m_curActionState = ESketchActionState::None;
}

void QSketchManager::redo()
{
	//qDebug() << "QSketchManager::redo";
	if (!m_currentSketch || m_currentSketch->m_deletedActors.size() == 0)
	{
		return;
	}

	Handle(QIVtkSelectionPipeline) actor = m_currentSketch->m_deletedActors.back();
	m_currentSketch->m_deletedActors.pop_back();

	actor->SetPipelineVisibility(true);
	m_currentSketch->m_actors.push_back(actor);

	m_mainWindow->FlushRender();
}

void QSketchManager::undo()
{
    //qDebug() << "QSketchManager::undo";
	if (!m_currentSketch || m_currentSketch->m_actors.size() == 0)
	{
		return;
	}

	Handle(QIVtkSelectionPipeline) actor = m_currentSketch->m_actors.back();
	m_currentSketch->m_actors.pop_back();

	actor->SetPipelineVisibility(false);
	m_currentSketch->m_deletedActors.push_back(actor);

	m_mainWindow->FlushRender();
}

gp_Trsf QSketchManager::GetLocalToGlobalTransform(const gp_Pnt& O, const gp_Dir& N, const gp_Dir& Right)
{
	gp_Trsf trsf = GetGlobalToLocalTransform(O, N, Right);
	trsf.Invert();
	return trsf;
}

gp_Trsf QSketchManager::GetGlobalToLocalTransform(const gp_Pnt& O, const gp_Dir& N, const gp_Dir& Right)
{
	// 构造局部坐标系：原点O，Z轴为N，X轴为Right，Y轴自动计算为N × Right
	gp_Ax3 localCoord(O, N, Right);

	// 生成从世界坐标系到局部坐标系的变换
	gp_Trsf trsf;
	trsf.SetTransformation(localCoord);

	return trsf;
}

void QSketchManager::CreateSketch(const gp_Pnt& O, const gp_Dir& N, const gp_Dir& Right)
{
	//gp_Trsf trsf = GetTransform(O, N, Right);

	//std::cout << "CreateSketch" << std::endl;

	// 1.隐藏所有actor
	m_mainWindow->SetCachedActorVisibility(false);
	// 2.创建新的原点坐标系

	// 3.改变interatror stytle的交互方式
	m_mainWindow->GetInteractorStyle()->Toggle2DMode(O, N, Right);

	m_mainWindow->SketchActionResponse(true);

	m_currentSketch = new QSketch(this, O, N, Right);
	m_sketchs.push_back(m_currentSketch);
}

void QSketchManager::CreateSketchByOperation(SketchOperation* op)
{
	// 1.隐藏所有actor
	m_mainWindow->SetCachedActorVisibility(false);
	// 2.创建新的原点坐标系

	// 3.改变interatror stytle的交互方式
	m_mainWindow->GetInteractorStyle()->Toggle2DMode(op->m_center, op->m_normal, op->m_right);

	m_mainWindow->SketchActionResponse(true);

	m_currentSketch = new QSketch(this, op->m_center, op->m_normal, op->m_right);
	m_sketchs.push_back(m_currentSketch);

	for (auto& featureShape : op->m_featureShapes)
	{
		Handle(QIVtkSelectionPipeline) actor = m_mainWindow->createActorFromFeatureShape(featureShape.get(), false);
		actor->Actor()->GetProperty()->SetLineWidth(3);
		m_currentSketch->m_actors.push_back(actor);
		actor->m_featureShape = featureShape;
	}

	m_mainWindow->FlushRender();
}

void QSketchManager::FinishCreateSketch()
{
	if (m_currentSketch == nullptr)
	{
		return;
	}
	// 清空shape
	m_currentSketch->m_featureShapes.clear();
	// 添加shape--->未来可能会对shape进行合并(多个edge变为wire)
	for (auto& actor : m_currentSketch->m_actors)
	{
		actor->SetPipelineVisibility(false);
		m_currentSketch->m_featureShapes.push_back(actor->m_featureShape);
	}
	// 创建actor
	for (auto& shape : m_currentSketch->m_featureShapes)
	{
		Handle(QIVtkSelectionPipeline) actor = m_mainWindow->createActorFromFeatureShape(shape.get(), true);
		actor->Actor()->GetProperty()->SetLineWidth(3);
		actor->m_featureShape = shape;
	}

	/*
	// 1.提取所有edge
	std::vector<TopoDS_Edge> edges;
	std::vector<TopoDS_Wire> wireExist; // 已经存在的wire
	for (auto& actor : m_currentSketch->m_actors)
	{
		TopoDS_Shape shape = actor->OccShape();
		// 理论上草图直接创建的都是edge
		if (shape.ShapeType() == TopAbs_EDGE)
		{
			TopoDS_Edge edge = TopoDS::Edge(shape);
			edges.push_back(edge);
		}
		if (shape.ShapeType() == TopAbs_WIRE)
		{
            TopoDS_Wire wire = TopoDS::Wire(shape);
			wireExist.push_back(wire);
		}
		// 隐藏actor
		actor->SetPipelineVisibility(false);
	}
	// 2.将edge转化为wire
	std::vector<TopoDS_Wire> wires = BuildWiresFromEdges(edges);
	wires.insert(wires.end(), wireExist.begin(), wireExist.end());
	std::cout << "wire num:" << wires.size() << std::endl;
	// 3.将wire转化为face
	TopoDS_Face face = CreateFaceWithHoles(wires);
	// 4.根据face生成actor
	Handle(QIVtkSelectionPipeline) faceActor = m_mainWindow->createBasicUnitActor(face, true);
	*/

	// 5.增加 history
	SketchOperation* op = new SketchOperation(tr("创建草图"), 
		m_currentSketch->m_N, m_currentSketch->m_R, m_currentSketch->m_O, m_currentSketch->m_featureShapes);
	m_mainWindow->GetHistoryManager()->applyOperation(op);

	// 6.恢复状态
	m_mainWindow->GetInteractorStyle()->ResetMode();
	m_mainWindow->SetCachedActorVisibility(true);
	m_mainWindow->SketchActionResponse(false);
	m_currentSketch = nullptr;
	m_pipelineIntersectionPoints.clear();
	if (m_currentCurveAction)
	{
        m_currentCurveAction->Reset();
	}
}

void QSketchManager::CreateSketchCurve(ESketchCurveType curveType)
{
	if (!m_currentSketch)
	{
		return;
	}

	ClearActionState();

	m_curActionState = ESketchActionState::CreateCurve;
	m_currentCurveAction = m_curveActions[curveType];
	m_currentCurveAction->StartCreate();
}

void QSketchManager::EndCreateSketchCurve(Handle(QIVtkSelectionPipeline) createActor)
{
	//std::cout << "QSketchManager::EndCreateSketchCurve" << std::endl;

	m_currentCurveAction->Reset();
	//m_currentCurveAction = nullptr;
	HandleEdgeIntersections(createActor);
	m_currentSketch->AddSketchCurve(createActor);
	//m_curActionState = ESketchActionState::None;
	m_currentCurveAction->StartCreate();
	m_currentSketch->m_deletedActors.clear();
}

void QSketchManager::filterSelectVertexType(EVertexType type, QAction* action)
{
	if (_selectedVertexTypes.count(type))
	{
		_selectedVertexTypes.erase(type);
		action->setChecked(false);
	}
	else
	{
		_selectedVertexTypes.insert(type);
		action->setChecked(true);
	}
}

gp_Dir QSketchManager::GetCurrentNormal()
{
	if (m_currentSketch)
	{
		return m_currentSketch->m_N;
	}

	return gp_Dir();
}

std::tuple<std::vector<TopoDS_Wire>, std::vector<TopoDS_Edge>> QSketchManager::PreprocessEdges(const std::vector<TopoDS_Edge>& edges)
{
	std::vector<TopoDS_Wire> closedWires;
	std::vector<TopoDS_Edge> nonClosedEdges;

	for (const auto& edge : edges) 
	{
		// 检查边是否有效
		TopoDS_Vertex V1, V2;
		TopExp::Vertices(edge, V1, V2);
		if (V1.IsNull() || V2.IsNull()) 
		{
			continue; // 剔除无效边
		}

		// 判断边是否闭合
		if (V1.IsSame(V2) || BRep_Tool::IsClosed(edge)) 
		{
			// 直接生成闭合线框
			BRepBuilderAPI_MakeWire wireMaker;
			wireMaker.Add(edge);
			if (wireMaker.IsDone()) 
			{
				closedWires.push_back(wireMaker.Wire());
			}
		}
		else 
		{
			nonClosedEdges.push_back(edge);
		}
	}

	return { closedWires, nonClosedEdges };
}

std::vector<TopoDS_Wire> QSketchManager::BuildWiresFromEdges(const std::vector<TopoDS_Edge>& edges) {
	std::vector<TopoDS_Wire> resultWires;
	// 步骤1：预处理，分离闭合边和非闭合边
	auto [closedWires, nonClosedEdges] = PreprocessEdges(edges);
	resultWires.insert(resultWires.end(), closedWires.begin(), closedWires.end());
	if (nonClosedEdges.empty()) return resultWires;

	// 步骤2：构建顶点-边映射（基于几何坐标）
	std::map<gp_Pnt, TopTools_ListOfShape, PntComparator> vertexEdgeMap;
	for (const auto& edge : nonClosedEdges) 
	{
		TopoDS_Vertex V1, V2;
		TopExp::Vertices(edge, V1, V2);
		gp_Pnt P1 = BRep_Tool::Pnt(V1);
		gp_Pnt P2 = BRep_Tool::Pnt(V2);

		vertexEdgeMap[P1].Append(edge);
		vertexEdgeMap[P2].Append(edge);
	}

	// 步骤3：遍历生成闭合线框
	TopTools_MapOfShape visitedEdges;
	const double tolerance = 0.01; // 自定义容差

	while (visitedEdges.Extent() < nonClosedEdges.size()) 
	{
		// 找到第一条未访问的边
		TopoDS_Edge startEdge;
		for (const auto& edge : nonClosedEdges) 
		{
			if (!visitedEdges.Contains(edge)) 
			{
				startEdge = edge;
				break;
			}
		}

		BRepBuilderAPI_MakeWire wireMaker;
		wireMaker.Add(startEdge);
		visitedEdges.Add(startEdge);

		// 记录起点和终点
		TopoDS_Vertex startV, endV;
		TopExp::Vertices(startEdge, startV, endV);
		gp_Pnt startPnt = BRep_Tool::Pnt(startV);
		gp_Pnt currentPnt = BRep_Tool::Pnt(endV);

		bool isClosed = false;
		while (!isClosed) 
		{
			bool foundNextEdge = false;
			auto it = vertexEdgeMap.find(currentPnt);
			if (it == vertexEdgeMap.end()) break;

			// 找到一条未被访问的关联边
			for (TopTools_ListIteratorOfListOfShape lit(it->second); lit.More(); lit.Next()) 
			{
				TopoDS_Edge nextEdge = TopoDS::Edge(lit.Value());
				// 已被访问则跳过
				if (visitedEdges.Contains(nextEdge)) continue;

				// 获得关联边的端点坐标
				TopoDS_Vertex nextV1, nextV2;
				TopExp::Vertices(nextEdge, nextV1, nextV2);
				gp_Pnt nextP1 = BRep_Tool::Pnt(nextV1);
				gp_Pnt nextP2 = BRep_Tool::Pnt(nextV2);

				currentPnt = nextP2; // 移动到终点

				// 如果终点是关联边的终点，则反转关联边
				if (nextP2.IsEqual(currentPnt, tolerance)) 
				{
					// 反转之后获取的坐标值没有发生变换
					nextEdge.Reverse();
					currentPnt = nextP1;
					//TopExp::Vertices(nextEdge, nextV1, nextV2); // 更新顶点
					//nextP1 = BRep_Tool::Pnt(nextV1); // 重新提取坐标
					//nextP2 = BRep_Tool::Pnt(nextV2);
				}

				wireMaker.Add(nextEdge);
				visitedEdges.Add(nextEdge);
				foundNextEdge = true;

				// 检查几何闭合性
				if (currentPnt.IsEqual(startPnt, tolerance)) 
				{
					isClosed = true;
				}
				break;
			}
			// 若不存在关联边，直接退出循环
			if (!foundNextEdge) break;
		}

		// 直接添加修复后的线框
		if (wireMaker.IsDone()) 
		{
			TopoDS_Wire wire = wireMaker.Wire();
			ShapeFix_Wire fixWire;
			fixWire.Load(wire);
			fixWire.Perform();
			// 闭合wire才添加
			if (BRep_Tool::IsClosed(wire))
			{
				resultWires.push_back(fixWire.Wire());
			}
		}
	}

	return resultWires;
}

TopoDS_Wire QSketchManager::FixWireOrientation(TopoDS_Wire& wire, bool isOuter)
{
	// 检查方向（外圈需逆时针，内圈顺时针）
	bool bIsClock = IsWireClockwise(wire);
	if (isOuter && bIsClock)
	{
		wire.Reverse(); // 反转为逆时针
	}
	else if (!isOuter && !bIsClock)
	{
		wire.Reverse(); // 反转为顺时针
	}
	return wire;
}

bool QSketchManager::IsWireClockwise(const TopoDS_Wire& wire)
{
	std::vector<gp_Pnt> vertices;

	// 提取顶点
	TopExp_Explorer edgeExplorer(wire, TopAbs_EDGE);
	TopoDS_Edge currentEdge = TopoDS::Edge(edgeExplorer.Current());
	TopoDS_Vertex firstStart, firstEnd;
	TopExp::Vertices(currentEdge, firstStart, firstEnd);
	vertices.push_back(BRep_Tool::Pnt(firstStart));
	vertices.push_back(BRep_Tool::Pnt(firstEnd));

	for (edgeExplorer.Next(); edgeExplorer.More(); edgeExplorer.Next()) 
	{
		currentEdge = TopoDS::Edge(edgeExplorer.Current());
		TopoDS_Vertex v1, v2;
		TopExp::Vertices(currentEdge, v1, v2);
		vertices.push_back(BRep_Tool::Pnt(v2));
	}

	// 计算有符号面积
	double signedArea = 0.0;
	int n = vertices.size();
	for (int i = 0; i < n; ++i) 
	{
		const gp_Pnt& p1 = vertices[i];
		const gp_Pnt& p2 = vertices[(i + 1) % n];
		signedArea += (p1.X() * p2.Y() - p2.X() * p1.Y());
	}
	signedArea /= 2.0;

	return signedArea < 0; // 返回是否为顺时针（CW）
}

bool QSketchManager::IsWireInside(const TopoDS_Wire& outer, const TopoDS_Wire& inner)
{
	// 生成外圈的面
	BRepBuilderAPI_MakeFace outerFaceMaker(outer);
	if (!outerFaceMaker.IsDone()) return false;
	TopoDS_Face outerFace = outerFaceMaker.Face();

	// 取内圈的一个顶点作为测试点
	TopoDS_Vertex aVertex;
	TopExp_Explorer exp(inner, TopAbs_VERTEX);
	if (!exp.More()) return false;
	aVertex = TopoDS::Vertex(exp.Current());
	gp_Pnt testPoint = BRep_Tool::Pnt(aVertex);

	// 分类器判断点是否在面内部
	BRepClass3d_SolidClassifier classifier(outerFace, testPoint, Precision::Confusion());
	return classifier.State() == TopAbs_IN;
}

TopoDS_Wire QSketchManager::FindOuterWire(std::vector<TopoDS_Wire>& wires)
{
	// #TODO:未考虑多层wire嵌套关系（存在多个外圈wire，会形成多个face）
	// #TODO:未考虑wire交叉情况
	for (auto& candidate : wires) 
	{
		bool isOuter = true;
		for (auto& other : wires) 
		{
			if (candidate.IsSame(other)) continue;
			if (IsWireInside(other, candidate)) 
			{ // 如果 candidate 被 other 包含
				isOuter = false;
				break;
			}
		}
		if (isOuter) 
		{
			return candidate; // 找到最外层线框
		}
	}
	qDebug() << "未找到外圈线框！";
	return TopoDS_Wire();
}

TopoDS_Face QSketchManager::CreateFaceWithHoles(std::vector<TopoDS_Wire>& wires)
{
	// 步骤1：修复所有线框方向（初始假设为外圈逆时针）
	//for (auto& wire : wires) 
	//{
	//	wire = FixWireOrientation(wire, /*isOuter=*/true);
	//}

	// 步骤2：确定外圈
	TopoDS_Wire outerWire = FindOuterWire(wires);
	std::vector<TopoDS_Wire> innerWires;

	// 步骤3：收集内圈（被外圈包含的线框）
	for (auto& wire : wires) 
	{
		if (!wire.IsSame(outerWire)/* && IsWireInside(outerWire, wire)*/) 
		{
			// 反转内圈方向为顺时针
			wire.Reverse();
			//TopoDS_Wire innerWire = FixWireOrientation(wire, /*isOuter=*/false);
			innerWires.push_back(wire);
		}
	}

	// 步骤4：生成面
	BRepBuilderAPI_MakeFace faceMaker(outerWire);
	for (const auto& inner : innerWires) 
	{
		faceMaker.Add(inner);
	}

	if (!faceMaker.IsDone()) 
	{
		qDebug() << "生成面失败！";
		return TopoDS_Face();
	}

	return faceMaker.Face();
}

TopoDS_Edge QSketchManager::GetSelectedEdge()
{
	TopoDS_Edge res;

	if (!m_actionCurveActor)
	{
		return res;
	}

	EFeatureType featureType = m_actionCurveActor->m_featureShape->_featureType;
	if (featureType != EFeatureType::Rectangle)
	{
		res = TopoDS::Edge(m_actionCurveActor->OccShape());
	}
	else
	{
		// 循环遍历长方体的每条边，判断点是否在线上
		TopExp_Explorer edgeExp(m_actionCurveActor->OccShape(), TopAbs_EDGE);
		while (edgeExp.More())
		{
			TopoDS_Edge temp = TopoDS::Edge(edgeExp.Current());
			if (IsPointOnEdge(m_currentIntersectionPoint, temp, 0.01))
			{
				res = temp;
				break;
			}
			edgeExp.Next();
		}
	}
	return res;
}

TopoDS_Edge QSketchManager::ExtendEdge(const TopoDS_Edge& edge, float scale)
{
	TopoDS_Edge res;

	Standard_Real uStart, uEnd;
	Handle(Geom_Curve) extendCurve = BRep_Tool::Curve(edge, uStart, uEnd);

	gp_Pnt firstPnt, lastPnt;
	firstPnt = extendCurve->Value(uStart);
	lastPnt = extendCurve->Value(uEnd);

	// 直线方向
	gp_Vec direction = (lastPnt - firstPnt).XYZ();
	direction.Normalize();
	// 中点
	gp_Pnt midPoint = (firstPnt + lastPnt) * 0.5;
	gp_Pnt newEndPnt = midPoint + gp_Pnt((direction * scale).XYZ());
	gp_Pnt newStartPnt = midPoint - gp_Pnt((direction * scale).XYZ());
	res = BRepBuilderAPI_MakeEdge(newStartPnt, newEndPnt);

	return res;
}

TopoDS_Edge QSketchManager::GetArcBasic(const TopoDS_Edge& edge)
{
	Standard_Real first, last;
	Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, first, last);

	if (curve.IsNull()) 
	{
		qDebug() << "Edge has no geometry.";
	}

	// 解包 Geom_TrimmedCurve（如果存在）
	Handle(Geom_Circle) circle;
	if (curve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) 
	{
		Handle(Geom_TrimmedCurve) trimmed = Handle(Geom_TrimmedCurve)::DownCast(curve);
		Handle(Geom_Circle) baseCircle = Handle(Geom_Circle)::DownCast(trimmed->BasisCurve());
		if (baseCircle.IsNull()) 
		{
            qDebug() << "Trimmed curve has no basis circle.";
		}
		circle = baseCircle;
	}
	else if (curve->DynamicType() == STANDARD_TYPE(Geom_Circle)) 
	{
		circle = Handle(Geom_Circle)::DownCast(curve);
	}
	else 
	{
        qDebug() << "Edge geometry is not a circle or trimmed circle.";
	}

	// 从 Geom_Circle 提取几何圆（gp_Circ）
	gp_Circ circ = circle->Circ();

	// 构造完整圆边（参数范围自动设为 0 ~ 2π）
	BRepBuilderAPI_MakeEdge makeEdge(circ);
	if (!makeEdge.IsDone()) 
	{
        qDebug() << "Failed to create full circle edge.";
	}

	return makeEdge.Edge();
}
